package com.turbo.cloud.core.trace;

import cn.hutool.core.util.StrUtil;
import com.turbo.cloud.core.constants.HeaderConstants;
import com.turbo.cloud.core.utils.CustomizerIdUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.util.Objects;

@Slf4j
public class TraceInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        TraceThreadLocal.remove();

        String traceId = getTraceId(request);
        TraceThreadLocal.setTraceId(StrUtil.isNotBlank(traceId) ? traceId : CustomizerIdUtil.id("TRC-", null));

        String clientId = getClientId(request);
        TraceThreadLocal.setClientId(clientId);

        String currentUser = getCurrentUser(request);
        TraceThreadLocal.setCurrentUser(StrUtil.isNotBlank(currentUser) ? currentUser : "NONE");

        MDC.put("clientId", TraceThreadLocal.getClientId());
        MDC.put("traceId", TraceThreadLocal.getTraceId());
        MDC.put("currentUser", TraceThreadLocal.getCurrentUser());
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //返回请求方
        response.setHeader(HeaderConstants.X_TRACE_ID, TraceThreadLocal.getTraceId());
        // 清空本地线程中的参数对象数据
        TraceThreadLocal.remove();
    }

    private String getTraceId(HttpServletRequest request) {
        // 先从header中获取，没有从params获取
        String header = request.getHeader(HeaderConstants.X_TRACE_ID);
        String param = request.getParameter(HeaderConstants.X_TRACE_ID);
        return StrUtil.isNotEmpty(header) ? header : param;
    }

    private String getClientId(HttpServletRequest request) {
        String clientId = request.getHeader(HeaderConstants.X_CLIENT_ID);
        return Objects.nonNull(clientId) ? clientId : "";
    }

    private String getCurrentUser(HttpServletRequest request) {
        String currentUser = request.getHeader(HeaderConstants.X_CURRENT_USER);
        return Objects.nonNull(currentUser) ? currentUser : "";
    }
}
